from flask import Flask, request, redirect, session, render_template, jsonify,send_from_directory

import uuid
import time
import hmac
import hashlib
import requests
from pyexpat.errors import codes

app = Flask(__name__,static_folder='static', static_url_path='/static')
app.secret_key = 'idp_secret_key'
app.config['SESSION_COOKIE_NAME'] = 'idp_session'

# 模拟用户数据库
users = {
    'liubo': {'id':1, 'password': '494619', 'username': '刘博','phone_number': '19903494619',
              'email': ''},
    'heming': {'id':2, 'password': '376301', 'username': '何鸣','phone_number': '15601376301',
              'email': ''},
    'chenyuxin': {'id':3, 'password': '522436', 'username': '陈雨欣','phone_number': '15779522436',
              'email': ''},
    'maruixi': {'id':4, 'password': '212576', 'username': '马瑞浠','phone_number': '18081212576',
              'email': ''},
    'duyutong': {'id':5, 'password': '503618', 'username': '杜宇彤','phone_number': '15910503618',
              'email': ''},
    'heleya': {'id':6, 'password': '327863', 'username': '何乐雅','phone_number': '18518327863',
              'email': ''},
    'qiaodawei': {'id':7, 'password': '231564', 'username': '乔大伟','phone_number': '17710231564',
              'email': ''},
    'wuyangrui': {'id':8, 'password': '418029', 'username': '武洋锐','phone_number': '1322418029',
              'email': ''}
}

# 模拟客户端数据库
clients = {
    'client1': {
        'client_secret': 'client1_secret',
        'redirect_uris': ['http://localhost:9000/auth/login'],
        'scope': 'openid profile'
    },
    'client2': {
        'client_secret': 'client2_secret',
        'redirect_uris': ['http://localhost:9010/auth/login'],
        'scope': 'openid profile'
    },
    'exhibition_id': {
            'client_secret': 'exhibition_secret',
            'redirect_uris': ['http://gem.wuyangrui:9000/auth/login'],
            'scope': 'openid profile'
    },
    'inner_id': {
            'client_secret': 'inner_secret',
            'redirect_uris': ['http://gem.wuyangrui:9000/auth/login'],
            'scope': 'openid profile'
    }
}


# 模拟授权码存储
authorization_codes = {}

# 模拟令牌存储
tokens = {}

# 存储已登录的客户端
logged_in_clients = {}

# 共享密钥
CLIENT_SECRETS = {
    'client1': 'client1_secret',
    'client2': 'client2_secret'
}

# 打印请求参数
# @app.before_request
# def log_request_info():
#     app.logger.debug('Request Headers: %s', request.headers)
#     app.logger.debug('Request Body: %s', request.get_data())
#     app.logger.debug('Request Args: %s', request.args)
#     app.logger.debug('Request Form: %s', request.form)
# #     app.logger.debug('Request JSON: %s', request.json)
#
# # 打印返回结果
# @app.after_request
# def log_response_info(response):
#     app.logger.debug('Response Status: %s', response.status)
#     app.logger.debug('Response Headers: %s', response.headers)
#     app.logger.debug('Response Data: %s', response.get_data())
#     return response


# 生成签名
def generate_signature(data, secret):
    return hmac.new(secret.encode(), data.encode(), hashlib.sha256).hexdigest()

@app.route('/')
def index():
    if 'user' not in session:
        return redirect('/oauth/login')
    return render_template('home.html',user=users[session['user']]['username'])
@app.route('/oauth/index')
def home():
    if 'user' not in session:
        return redirect('/oauth/login')
    return render_template('home.html',user=users[session['user']]['username'])

@app.route('/oauth/login', methods=['GET', 'POST'])
def login():
    client_id = request.args.get('client_id', None)
    redirect_uri = request.args.get('redirect_uri', None)
    state = request.args.get('state', None)

    if request.method == 'POST':
        data = request.get_json()

        username = data.get('username')
        password = data.get('password')
        if username in users and users[username]['password'] == password:
            session['user'] = username
            code = str(uuid.uuid4())
            if client_id is None:
                # return redirect('/')
                return jsonify({'status': 200})
            else:
                authorization_codes[code] = {'client_id': client_id, 'user': username, 'expires': time.time() + 300}
                # return redirect(f"{redirect_uri}?code={code}&state={state}")
                return jsonify({'status': 201, 'code': code, 'state': state})
        return 'Invalid credentials', 401
    return render_template('login.html')

@app.route('/oauth/authorize', methods=['GET'])
def authorize():
    if 'user' not in session:
        return redirect(f"/oauth/login?client_id={request.args.get('client_id')}&redirect_uri"
                        f"={request.args.get('redirect_uri')}&state={request.args.get('state')}")
    client_id = request.args.get('client_id')
    if client_id in clients:
        code = str(uuid.uuid4())
        authorization_codes[code] = {'client_id': client_id, 'user': session['user'], 'expires': time.time() + 300}
        return redirect(f"{request.args.get('redirect_uri')}?code={code}&state={request.args.get('state')}")
    return 'Invalid client', 400

@app.route('/oauth/token', methods=['POST'])
def issue_token():
    print("/oauth/token===============")
    print(request.form)
    grant_type = request.form.get('grant_type')
    if grant_type == 'refresh_token':
        refresh_token = request.form.get('refresh_token')
        if refresh_token in tokens:
            token_data = tokens[refresh_token]
            new_access_token = str(uuid.uuid4())
            new_refresh_token = str(uuid.uuid4())
            tokens[new_access_token] = {
                'access_token': new_access_token,
                'refresh_token': new_refresh_token,
                'user': token_data['user'],
                'expires_in': 3600
            }
            tokens[new_refresh_token] = tokens[new_access_token]
            return jsonify({
                'access_token': new_access_token,
                'refresh_token': new_refresh_token,
                'token_type': 'Bearer',
                'expires_in': 3600
            })
        return 'Invalid refresh token', 400
    if grant_type == 'authorization_code':
        client_id = request.form.get('client_id')
        client_secret = request.form.get('client_secret')
        code = request.form.get('code')
        if client_id in clients and clients[client_id]['client_secret'] == client_secret:
            if code in authorization_codes and authorization_codes[code]['client_id'] == client_id:
                if authorization_codes[code]['expires'] > time.time():
                    access_token = str(uuid.uuid4())
                    refresh_token = str(uuid.uuid4())
                    tokens[access_token] = {
                        'access_token': access_token,
                        'refresh_token': refresh_token,
                        'user': authorization_codes[code]['user'],
                        'expires_in': 3600
                    }
                    tokens[refresh_token] = tokens[access_token]
                    print(tokens)
                    return jsonify({
                        'access_token': access_token,
                        'token_type': 'Bearer',
                        'expires_in': 3600,
                        'refresh_token': refresh_token
                    })
                return 'Authorization code expired', 400
            return 'Invalid authorization code', 400
        return 'Invalid client credentials', 401

@app.route('/oauth/userinfo')
def userinfo():
    token = request.headers.get('Authorization')
    print("/oauth/userinfo===============")
    print(token)
    if token and token.startswith('Bearer '):
        token = token.split(' ')[1]
        print(tokens)
        if token in tokens:
            account = tokens[token]['user']
            print("account=" + str(account))
            print(users)
            if account in users:
                return jsonify({
                    'id':users[account]['id'],
                    'account': account,
                    'username': users[account]['username'],
                    'phone_number': users[account]['phone_number'],
                    'email': users[account]['email']
                })
    return 'Unauthorized', 401

@app.route('/oauth/register_logout', methods=['POST'])
def register_logout():
    data = request.json
    client_id = data.get('client_id')
    user = data.get('user')
    logout_url = data.get('logout_url')
    if client_id in clients:
        if user not in logged_in_clients.get(client_id, {}):
            logged_in_clients.setdefault(client_id, {}).setdefault(user, [])
        logged_in_clients[client_id][user].append(logout_url)
        return 'Logout URL registered', 200
    return 'Invalid client', 400
@app.route('/oauth/logout', methods=['GET'])
def logout_all():
    user = session.get('user')
    if user:
        # 清除与该用户相关的所有令牌
        tokens_to_remove = [token for token, data in tokens.items() if data.get('user') == user]
        for token in tokens_to_remove:
            tokens.pop(token, None)

        # 清除 IdP 的会话
        session.pop('user', None)
        return redirect('/oauth/index')
    return  redirect('/oauth/index')


@app.route('/.well-known/pki-validation/fileauth.txt')
def serve_domain_verification():
    return send_from_directory('static/well-known/pki-validation', 'fileauth.txt')

if __name__ == '__main__':
    app.run(port=5000,debug=True,host='0.0.0.0')